Del1:
a) Kompilér mygpio_basic.
i denne del af opgaven tester vi om vores tool chaine virker korekt. Dette gøres ved at kompilerer programmet.

b) Sammenhold eksemplerne 5.6 og 5.7 i bogen og vær opmærksom på forskellene. Bemærk at der i 5.7 benyttes en makro til pre-compileren for at få den til at generere 8 ens funktioner: glow_led0, glow_led1....glow_led7. Start med at kigge på init og exit metoderne (her: init / cleanup) og bemærk at der nu er tilføjes en klasse og kobjects som som får filsvarende filer i sysfs. I den seneste version af kernen, erstattes device_class_create med class_create og denne udfører selv manipulation på kobjekter, så dette kan udelades ifht eksempel 5.7. Eksemplerne benytter desuden en "parport" bus, hvilket gør at led driveren registreres som en parport driver. Vores eksempel er mere simpelt og dette skridt kan også udelades.

i denne del af opgaven sammenholdes eksemplerne eksemplerne 5.6 og 5.7

c) Tilføj en sysfs klasse "mygpio", således at vores driver får sin egen klasse under /sys/class/. Benyt metoderne beskrevet nedenfor i jeres init/exit metoder:
Global
//***************************************************************
// globale variabler
//***************************************************************
static struct class *myGpio_class; //Klassen som devicet tilhører.
struct device *myGpio_device;

Init
//**************************************************************************
//oprettelse af classe når denne oprettes oprettes der en mappe under sysfs
//**************************************************************************
    mygpio_class = class_create(THIS_MODULE, "myGpio");
    if(IS_ERR(myGpio_class))
    {
      printk("Class not created\n"); //Fejlmeddelse ved fejl
    }
//**************************************************************************
//Oprettelse af en fil under den  mappe i sysfs.
//**************************************************************************
    myGpio_device = device_create(mygpio_class, NULL, devno, NULL, "myGpio");
    printk("mygpio driver successfull initialized");

Exit
//*********************************************************
// nedlæggelse af filer
//********************************************************
device_destroy(mygpio_class, devno); //Nedlæggelse af devic
class_destroy(mygpio_class); //Nedlæggelse af mappen mygpio i sysfs

d) Kompiler og kopier modulet til target. Lav to ssh forbindelser til target. På den ene startes "udevadm monitor" og via den anden forbindelse indsættes modulet. Bemærk hvad som sker og undersøg forandringerne i /sys/class, samt under /dev/ med ls -l.

i denne del af opgaven oprettes der to ssh forbindelser fra de to separatåbnede terminaler til devkitet i den ene startes udevadm monitor og fra den anden terminal indsættes
vores kernemodul
vi kan ud fra udskriften på terminalvinduet hvorfra vi har åbnet udevadm monitor se at der er oprettet en mappe kaldet mygpio ligeledes ses det under dev/ at mygpio objektet
er registreret og at denne har fået tildelt de forudefinerede minor/major numre
nedenfor kan udskreften fra terminalen med udevadm ses.

KERNEL[233.531550] add      /module/mygpio_basic (module)
UDEV  [233.538844] add      /module/mygpio_basic (module)
KERNEL[233.544459] add      /class/myGpio (class)
UDEV  [233.551357] add      /class/myGpio (class)
KERNEL[233.556240] add      /devices/virtual/myGpio/mygpio (myGpio)
UDEV  [233.571255] add      /devices/virtual/myGpio/mygpio (myGpio)
2000 Jan  1 00:03:50 beagleboard [  233.632476] Mygpio Module Inserte

vi kan også finde mappen ved at bruge ls -l under /sys/class

neden under ses udskriften i terminalen for /dev/

e) Ændr driveren til at bruge dynamisk allokering af major numre. Ændr linien med "register_chr_dev_region" til:

Ændr driveren til at bruge dynamisk allokering af major numre. Ændr linien med "register_chr_dev_region" til
følgende linje ændres
if((err=register_chrdev_region(devno,gpio_len, "myGpio"))<0){
til
if((err=alloc_chrdev_region(&devno, 0, gpio_len, "myGpio"))<0){

de fårtagede ændring gør at mygpio får tildelt tilfældige numre.
nedenfor ses outputtet på terminalen.
crw-------   1  root     root      233       0 Jan  1 00:03 myGpio

f) Opret en attribute med tilhørende show/store metoder. Show metoden skal udelukkende lave en printk("hello from show"), den anden venter vi lidt med... Benyt nedenstående metoder.
Global
static ssize_t gpio_value_show(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t gpio_value_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size);
 
struct device_attribute mygpio_attr = __ATTR(name, 0777, gpio_value_show, gpio_value_store);
Init
device_create_file(mygpio_device, &mygpio_attr);
Exit
device_remove_file(mygpio_device, &mygpio_attr);

g) Gør som i (e), men udtag dog først det gamle modul. bemærk at der er kommet en folder med forskellige attributter, incl den netop oprettede. Lav en cat på attributten og check i dmesg om du får en "hello from show".

det gamle modul udtages med rmmod hvorefter at det nye modul indsættes med insmod. hvorefter vi kører en cat vores
atribute fil /sys/class/mygpio/mygpio/output og en dmesg. hvorefter voresder fremkommer "hello from show".

h) Et hvert device kan gemme private data i driveren. Til dette benyttes drvdata som er en void pointer i "device_create" metoden. Show/store metoderne har hverisær en device pointer, således at man ved med hvilket device de er kaldt. Vha device pointeren kan de private data udtrækkes vha "dev_get_data" metoden. Opret en int gpio_no = 138 i init og tilføj referencen til denne som parameteren drvdata i "device_create". modificér nu din "show" metode til vise denne værdi, hertil benyttes metoden:
vi tilføjer følgende kode
int gpio_no = 138;
 
// init
c_d = device_create(mygpio_class, NULL, devno, &gpio_no, "mygpio");
 
// gpio_value_show
  int *pVal = dev_get_drvdata(dev);
  printk("device gpio no: %d\n", *pVal);

når der køres en cat fås "Hello from show device gpio no: 138"
i) Udfyld "store" metoden med indholdet vist og verificer at du nu kan sætte gpio porten både vha write til devicet oprettet under /dev/ samt ved at skrive til attributten.
følgende kode indsættes
static ssize_t gpio_value_store(struct device *dev,
        struct device_attribute *attr, const char *buf, size_t size)
{
 int *num = dev_get_drvdata(dev);
 ssize_t ret = -EINVAL;
 char *after;
 unsigned long value = simple_strtoul(buf, &after, 10);
 size_t count = after - buf;
 if (isspace(*after))
   count++;
 
 
 printk("using Store to set gpio #%i to %i\n", *num, (int)value);
 gpio_set_value(*num, value);
 return count;
}
når vi skriver til filen ved hjælp af write til vores device fås samme output som ved at skrive til attributten.
[  112.003784] using Store to set gpio #138 to 1

J) Evt. prøv at oprette en regel under /etc/udev/rules.d som giver gpio device't et andet navn.
der tilføjes en regl under "/etc/udev/rules.d" for at give modulet et andet navn.
KERNEL=="mygpio", NAME="nyt_gpio"
dette giver gpio devicet navnet nyt_gpio